package com.inforim.cognos;

import java.math.BigInteger;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.axis.client.Stub;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.cognos.developer.schemas.bibus._3.BaseClass;
import com.cognos.developer.schemas.bibus._3.ContentManagerServiceStub;
import com.cognos.developer.schemas.bibus._3.PropEnum;
import com.cognos.developer.schemas.bibus._3.QueryOptions;
import com.cognos.developer.schemas.bibus._3.SearchPathMultipleObject;
import com.cognos.developer.schemas.bibus._3.Sort;
import com.inforim.cognos.utils.CognosUtils;

public abstract class BaseCognosClient implements CognosClient {

	static Log log = LogFactory.getLog(BaseCognosClient.class);

	public BaseClass load(String path, Stub stub) {
		return this.query(path, null, null, null, stub)[0];
	}

	public BaseClass[] query(String path, PropEnum[] props, Sort[] sorts,
			QueryOptions options, Stub stub) {
		return this.search(path, SCOPE_OBJECT, props, sorts, options, 0, 0,
				stub);
	}

	public BaseClass[] search(String path, int scope, PropEnum[] props,
			Sort[] sorts, QueryOptions options, long skip, long size, Stub stub) {
		if (null == stub) {
			stub = this.getService("ContentManagerServiceStub");
		}
		boolean useSortProps = false;
		int sortPropsSize = 0;
		PropEnum[] sortProps = null;
		PropEnum[] searchProps = null;
		BaseClass[] result = null;
		// query search path
		String searchPath = CognosUtils.getSearchPath(path, scope);
		// query search props
		if (null == props) {
			props = new PropEnum[] { PropEnum.searchPath, PropEnum.defaultName,
					PropEnum.objectClass, PropEnum.storeID,
					PropEnum.searchPath };

		}
		// query search sort
		if (null == sorts) {
			sorts = new Sort[0];
		} else {
			if (useSortProps) {
				sortProps = new PropEnum[sorts.length];
				for (int i = 0; i < sorts.length; i++) {
					// sortProps[i] = sorts[i].getPropName();
					PropEnum pei = sorts[i].getPropName();
					boolean exists = false;
					for (int j = 0; j < props.length; j++) {
						PropEnum pej = props[j];
						if (pej.equals(pei)) {
							exists = true;
						}
					}
					if (!exists) {
						sortProps[sortPropsSize] = pei;
						sortPropsSize++;
					}
				}
			}
		}
		if (useSortProps && null != sortProps) {
			searchProps = new PropEnum[props.length + sortPropsSize];
			for (int i = 0; i < props.length; i++) {
				searchProps[i] = props[i];
			}
			for (int i = 0; i < sortProps.length; i++) {
				if (null != sortProps[i]) {
					searchProps[props.length + i] = sortProps[i];
				}
			}
		} else {
			searchProps = props;
		}
		// query options
		if (null == options) {
			options = new QueryOptions();
			if (skip > 0 || size > 0) {
				options.setSkipObjects(BigInteger.valueOf(skip));
				options.setMaxObjects(BigInteger.valueOf(size));
			}
		}
		if (null != stub) {
			try {
				ContentManagerServiceStub port = (ContentManagerServiceStub) stub;
				// log.debug("*** query.xpath: " + searchPath + " ***");
				result = port.query(new SearchPathMultipleObject(searchPath),
						searchProps, sorts, options);
				if (null == result) {
					log.error("content manager service query failed");
				}
				// result counts
				if (result.length <= 0) {
					// log.error("no published packages or reports.");
				}
			} catch (Exception ex) {
				log.error("error: ", ex);
			}
		}
		return result;
	}

	public String getGateway() {
		return gateway;
	}

	public void setGateway(String gateway) {
		this.gateway = gateway;
	}

	public String getDispatch() {
		return dispatch;
	}

	public void setDispatch(String dispatch) {
		this.dispatch = dispatch;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getNamespace() {
		return namespace;
	}

	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}

	public String getPassport() {
		return passport;
	}

	public void setPassport(String passport) {
		this.passport = passport;
	}

	public String getCamid() {
		return camid;
	}

	protected void setCamid(String camid) {
		this.camid = camid;
	}

	public String getFullname() {
		return fullname;
	}

	protected void setFullname(String fullname) {
		this.fullname = fullname;
	}

	public String getUid() {
		String uid = null;
		String camid = this.getCamid();
		if (null != camid) {
			String camstr = camid;
			if (camid.startsWith("CAMID(") && camid.endsWith(")")) {
				camstr = camid.substring("CAMID(".length(), camid.length() - 1);
			}
			if (camstr.startsWith("\"") && camstr.endsWith("\"")) {
				camstr = camstr.substring(1, camstr.length() - 1);
			}
			uid = camstr;
		}

		if (null == uid) {
			uid = this.getUsername();
		}
		return uid;
	}

	@SuppressWarnings("unchecked")
	public void setPlugin(String name, CognosPlugin plugin) {
		plugin.setClient(this);
		plugins.put(name, plugin);
	}

	public CognosPlugin getPlugin(String name) {
		if (plugins.containsKey(name)) {
			return (CognosPlugin) plugins.get(name);
		}
		return null;
	}

	private String gateway;

	private String dispatch;

	private String username;

	private String password;

	private String namespace;

	private String passport;

	private String camid;

	private String fullname;

	@SuppressWarnings("rawtypes")
	private Map plugins = new LinkedHashMap();

}
